
package todolist.gui;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import todolist.logic.MainController;

/**
 * Application driver class. View class too.
 * @author Lina
 * @author YouLi
 */
public class GUI implements KeyListener {
	
	private static final int COMMAND_MAXLENGTH = 500;

	public static void main(String[] args) {
		new GUI();
	}
	
	// member GUI attributes
	
	private JLabel _lblUrgentTask, _lblNavigation, _lblDisplay, _lblCommand, _lblFeedback;
	private JTextArea _txtUrgentTaskDisplay, _txtDisplay;
	private JTextPane _txtNavigationDisplay;
	private JScrollPane _objDisplayPane;
	private JTextField _txtCommand;
	private JFrame _objGUIFrame;

	// view --> controller facade
	private MainController _objMC;

	private GUI () {
		_objMC = MainController.getInstance();
		_objMC.init();
		createAndShowGUI();
		refreshAllDisplays();
	}
	
	// private init GUI methods
	
	/**
	 * Create, set up, display JFrame and all components within.
	 */
	private void createAndShowGUI() {
		// create and set up the JFrame
		_objGUIFrame = new JFrame("ToDoList Manager");
		_objGUIFrame.setContentPane(new JLabel(createImageIcon("image.png")));
		_objGUIFrame.getContentPane().setLayout(null);
		_objGUIFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
		initAllComponents();
		// display the window
		_objGUIFrame.setVisible(true);
		_objGUIFrame.setSize(1200, 700);
		_objGUIFrame.setResizable(false);
		_txtCommand.requestFocusInWindow();
	}

	/**
	 * Create, set up all components.
	 */
	private void initAllComponents() {
		initLabels();
		initUrgentTaskDisplay();
		initNavigationDisplay();
		initDisplay();
		initCommand();
		initInputMap();
	}

	/**
	 * Create, set up 5 labels.
	 */
	private void initLabels() {
		ImageIcon imgUrgentTask = createImageIcon("urgentTaskLabel.png");
		ImageIcon imgNavigation = createImageIcon("navigation.png");
		ImageIcon imgDisplay = createImageIcon("displayTask.png");
		ImageIcon imgCommand = createImageIcon("commandLbl.png");
		_lblUrgentTask = new JLabel(imgUrgentTask);
		_lblNavigation = new JLabel(imgNavigation);
		_lblDisplay = new JLabel(imgDisplay);
		_lblCommand = new JLabel(imgCommand);
		_lblFeedback = new JLabel("Feedback :");
		_lblUrgentTask.setBounds(30, 40, 331, 28);
		_lblNavigation.setBounds(30, 328, 331, 28);
		_lblDisplay.setBounds(390, 40, 785, 28);
		_lblCommand.setBounds(30, 532, 1150, 28);
		_lblFeedback.setOpaque(true);
		_lblFeedback.setBackground(Color.BLACK);
		_lblFeedback.setForeground(Color.WHITE);
		_lblFeedback.setBounds(30, 615, 1150, 35);
		Container objContentPane = _objGUIFrame.getContentPane();
		objContentPane.add(_lblUrgentTask);
		objContentPane.add(_lblNavigation);
		objContentPane.add(_lblDisplay);
		objContentPane.add(_lblCommand);
		objContentPane.add(_lblFeedback);
	}

	/**
	 * Create, set up urgent tasks at top left.
	 */
	private void initUrgentTaskDisplay(){
		_txtUrgentTaskDisplay = new JTextArea();
		_txtUrgentTaskDisplay.setFocusable(false);
		_txtUrgentTaskDisplay.setEditable(false);
		_txtUrgentTaskDisplay.setLineWrap(true);
		_txtUrgentTaskDisplay.setBounds(30, 68, 331, 251);
		Container objContentPane = _objGUIFrame.getContentPane();
		objContentPane.add(_txtUrgentTaskDisplay);
	}

	/**
	 * Create, set up navigation commands at middle left.
	 */
	private void initNavigationDisplay(){
		_txtNavigationDisplay = new JTextPane();
		_txtNavigationDisplay.setFocusable(false);
		_txtNavigationDisplay.setEditable(false);
		_txtNavigationDisplay.setBounds(30, 358, 331, 165);
		Container objContentPane = _objGUIFrame.getContentPane();
		objContentPane.add(_txtNavigationDisplay);
	}

	/**
	 * Create, set up display area at top right.
	 */
	private void initDisplay() {
		_txtDisplay = new JTextArea();
		_txtDisplay.setFocusable(false);
		_txtDisplay.setEditable(false);
		_txtDisplay.setLineWrap(true);
		_objDisplayPane = new JScrollPane(_txtDisplay);
		_objDisplayPane.setBounds(390, 68, 783, 453);
		Container objContentPane = _objGUIFrame.getContentPane();
		objContentPane.add(_objDisplayPane);
	}

	/**
	 * Create, set up command input area at bottom.
	 */
	private void initCommand(){
		_txtCommand = new JTextField();
		_txtCommand.setDocument(new JTextFieldLimit(COMMAND_MAXLENGTH));
		_txtCommand.setFocusable(true);
		_txtCommand.setBounds(30, 557, 1150, 60);
		_txtCommand.addKeyListener(this);
		Container objContentPane = _objGUIFrame.getContentPane();
		objContentPane.add(_txtCommand);
	}

	/**
	 * Set up input map for handling scrolling.
	 */
	private void initInputMap() {
		InputMap objIm = _objDisplayPane.getVerticalScrollBar().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
		objIm.put(KeyStroke.getKeyStroke("DOWN"), "positiveUnitIncrement");
		objIm.put(KeyStroke.getKeyStroke("UP"), "negativeUnitIncrement");
		objIm.put(KeyStroke.getKeyStroke("PAGE_DOWN"), "positiveBlockIncrement");
		objIm.put(KeyStroke.getKeyStroke("PAGE_UP"), "negativeBlockIncrement");
	}

	/**
	 * Creates and returns an image based on given image name.
	 */
	private ImageIcon createImageIcon(String pstrName) {
		String strPath = "images/" + pstrName;
		try {
			return new ImageIcon(ImageIO.read(new File(strPath)));
		} catch (IOException objEx) {
			JOptionPane.showMessageDialog(
				_objGUIFrame, "Couldn't find file: " + strPath, "File Not Found", // parent, message, title, messageType, icon
				JOptionPane.WARNING_MESSAGE, null);
			return null;
		}
	}
	
	private class JTextFieldLimit extends PlainDocument {
		
		private static final long serialVersionUID = 1L;
		private int _intLimit;

		private JTextFieldLimit(int pintLimit) {
			super();
			_intLimit = pintLimit;
		}

		/**
		 * Set max length.
		 */		
		public void insertString(int pintOffset, String pstrData,
			AttributeSet pobjAttr) throws BadLocationException {
			if (pstrData == null)
				return;
			if ((getLength() + pstrData.length()) <= _intLimit)
				super.insertString(pintOffset, pstrData, pobjAttr);
		}
		
	}

	// private pull data methods

	/**
	 * Pull data for all 5 display areas.
	 */
	private void refreshAllDisplays() {
		_txtUrgentTaskDisplay.setText(_objMC.getUrgentTasks());
		_txtNavigationDisplay.setText(_objMC.getNavigation());
		_txtDisplay.setText(_objMC.getDisplay());
		_txtCommand.setText(_objMC.getCommand());
		_lblFeedback.setText(_objMC.getFeedback());
	}
	
	// key events
	
	@Override
	public void keyPressed(KeyEvent pobjEvent) {
		if (pobjEvent.getKeyCode() != KeyEvent.VK_ENTER)
			return;
		// only handle enter keyPressed
		_objMC.executeCommand(_txtCommand.getText());
		refreshAllDisplays();
	}

	@Override public void keyReleased(KeyEvent pobjEvent) {} // do nothing
	@Override public void keyTyped(KeyEvent pobjEvent) {} // do nothing

}
